#include "recognition.h"
#include "ui_recognition.h"

recognition::recognition(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::recognition)
{
    ui->setupUi(this);
}

recognition::~recognition()
{
    delete ui;
}

void recognition::openfun()
{
    // 初始化级联分类器，加载人脸数据模型
   classifier = CascadeClassifier("D:/opencv/opencv3.4-install/install/etc/haarcascades/haarcascade_frontalface_alt2.xml");
   // 打开摄像头
   if(vc.open(0)) // 打开第一个摄像头
   {
       qDebug() << "摄像头打开成功！";
       timer = new QTimer(this);
       timer->setSingleShot(false);
       timer->setInterval(50); // 20帧
       connect(timer,SIGNAL(timeout()),this,SLOT(timeoutSlot()));
       timer->start();
   }
}


/**
 * @brief Dialog::blackSrc
 * 标记人脸检测有效区域
 */
void recognition::blackSrc()
{
    int rectSize = 300;
    // 有效区域的坐标
    int x = src.cols/2 - rectSize/2;
    int y = src.rows/2 - rectSize/2;
    // 矩形对象
    r = Rect(Point(x,y),Size(rectSize,rectSize));
    // 画框
    rectangle(src,r,Scalar(255,255,255));
    // 遍历列
    for(int x = 0;x<src.cols;x++)
    {
        // 每一行
        for(int y = 0;y<src.rows;y++)
        {
            // 判断当前像素点是否不在矩形中
            if(!r.contains(Point(x,y)))
            {
                 // 周围变暗
                Vec3b& v = src.at<Vec3b>(Point(x,y));
                v[0] = saturate_cast<uchar>(v[0]-50);
                v[1] = saturate_cast<uchar>(v[1]-50);
                v[2] = saturate_cast<uchar>(v[2]-50);
            }
        }
    }
}

void recognition::findFace()
{
    // 使用一个矩阵存储灰度图像，可以提升处理速度
    Mat gray;
    // 从原始图像中扣出300x300小图
    Mat midSrc = src(r);
    // BGR → GRAY
    cvtColor(midSrc,gray,CV_BGR2GRAY);
    qDebug() << "灰度图是否为空：" << gray.empty();
    // 使用级联分类器在绘图中找人脸，这些人脸的数据存在向量中
    classifier.detectMultiScale(gray,vec_findfaces);
    // 如果有人脸就画红框
    if(vec_findfaces.size() > 0)
    {
        qDebug() << "人脸数量：" << vec_findfaces.size();
        for(int i=0;i<vec_findfaces.size();i++)
        {
            // 取出每张人脸的矩形数据
            Rect faceRect = vec_findfaces.at(i);
            // 画框
            rectangle(midSrc,faceRect,Scalar(0,0,255),2);
        }
        QMessageBox::information(this, "information", "人脸识别成功！");
        // 停止定时器
        if (timer && timer->isActive())
        {
            timer->stop();
            delete timer;
        }

        // 关闭摄像头
        if (vc.isOpened())
        {
            vc.release();
            qDebug()<<"停止";
        }
          ui->label->setText(" ");
        qDebug()<<"停止";
    }
}
/**
 * @brief Dialog::showSrc
 * 在Qt界面上显示
 */
void recognition::showSrc()
{
    // BGR → RGB
    Mat rgb;
    cvtColor(src,rgb,CV_BGR2RGB);

    // Mat → QImage（Qt的图像计算类）
    QImage img(rgb.data, // 数据来源
               rgb.cols, // 宽度
               rgb.rows, // 高度
               rgb.cols*rgb.channels(), // 每一行的总通道数
               QImage::Format_RGB888 // 每个通道的深度 0-255 2^8
               );
    // QImage → QPixmap
    QPixmap pic = QPixmap::fromImage(img);
    // 设置给组件
    ui->label->setPixmap(pic);
    ui->label->resize(pic.width(),pic.height());
}

void recognition::timeoutSlot()
{
    // 1. 提取一张图片
    vc >> src;
    if(!src.empty())
        qDebug() << "采集到数据！";
    else
    {
        qDebug() << "图像采集失败！";
        return;
    }
    // 2. 选取检测有效区域
    blackSrc();
    // 3. 查找人脸
    findFace();
    // 4. 显示图像
    showSrc();
}

void recognition::stopSlot()
{
    // 停止定时器
    if (timer && timer->isActive())
    {
        timer->stop();
        delete timer;
    }

    // 关闭摄像头
    if (vc.isOpened())
    {
        vc.release();
        qDebug()<<"停止";
    }
     // ui->label->setText(" ");
    qDebug()<<"停止";
}

